1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=UTF-8">
5 <meta http-equiv=
"Content-Style-Type" content=
"text/css">
7 <meta name=
"Generator" content=
"Cocoa HTML Writer">
8 <meta name=
"CocoaVersion" content=
"824.48">
9 <style type=
"text/css">
10 p
.p1
{margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica
}
11 p
.p2
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; min-height: 14.0px}
12 p
.p3
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
}
13 p
.p4
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
}
14 p
.p5
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; min-height: 12.0px}
15 p
.p6
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #bf0000}
16 p
.p7
{margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica
}
17 p
.p8
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; color: #0000bf}
18 span
.s1
{color: #0000bf}
19 span
.s2
{color: #0000bf}
20 span
.s3
{color: #bf0000}
21 span
.s4
{color: #000000}
22 span
.s5
{color: #007300}
23 span
.s6
{text-decoration: underline
; color: #0000bf}
24 span
.s7
{font: 12.0px Helvetica
}
25 span
.Apple-tab-span
{white-space:pre
}
29 <p class=
"p1"><b>Math on patterns
</b></p>
30 <p class=
"p2"><br></p>
31 <p class=
"p3">Often, there is not a pattern that delivers exactly the desired result by itself. But, other operations can be applied to patterns, to manipulate one pattern's output and turn it into something else.
</p>
32 <p class=
"p2"><br></p>
33 <p class=
"p3">Some of these operations look like things you would do to an array, but there is a critical difference. Doing math on an array performs the operation on every array item all at once. By contrast, patterns are
"lazy" -- they evaluate one value at the time, only when asked, and they only do as much as they need to do to deliver the next value. An operation on a pattern produces another pattern that remembers the work that is to be done. Making a stream out of the composite pattern creates the structure to perform the operation upon request.
</p>
34 <p class=
"p2"><br></p>
35 <p class=
"p3">For example, multiplying a pattern by a number produces a
"binary operator pattern":
<a href=
"../Patterns/Pbinop.html"><span class=
"s1">Pbinop
</span></a>. Looking at the Pbinop's variables reveals everything that is needed to reconstruct the operation on demand.
</p>
36 <p class=
"p2"><br></p>
37 <p class=
"p4">p =
<span class=
"s2">Pwhite
</span>(
1,
5,
<span class=
"s2">inf
</span>) *
2;
<span class=
"Apple-tab-span"> </span><span class=
"s3">// a Pbinop
</span></p>
38 <p class=
"p5"><br></p>
39 <p class=
"p4">p.operator
<span class=
"Apple-tab-span"> </span><span class=
"s3">// == '*'
</span></p>
40 <p class=
"p6"><span class=
"s4">p.a
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// == a Pwhite
</p>
41 <p class=
"p6"><span class=
"s4">p.b
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// ==
2</p>
42 <p class=
"p2"><br></p>
43 <p class=
"p3">In other words, the multiplication here produces not the result of a single multiplication, but a template for an infinite stream of multiplications to follow.
</p>
44 <p class=
"p2"><br></p>
45 <p class=
"p7"><b>Math on patterns
</b></p>
46 <p class=
"p2"><br></p>
47 <p class=
"p3">Not only can patterns generate numbers, but they also support all the standard math operators: unary (abs, reciprocal, etc.), binary (+, -, *, /, **, min, max, etc.) and n-ary (clip, wrap, fold, linlin, linexp, etc.) operators are all valid with patterns.
</p>
48 <p class=
"p2"><br></p>
49 <p class=
"p6">// Random integers,
1-
5</p>
50 <p class=
"p4"><span class=
"s2">Pwhite
</span>(
1,
5,
<span class=
"s2">inf
</span>).asStream.nextN(
10);
</p>
51 <p class=
"p5"><br></p>
52 <p class=
"p6">// Random integers
1-
5, multiplied by two gives even integers
2-
10</p>
53 <p class=
"p4">(
<span class=
"s2">Pwhite
</span>(
1,
5,
<span class=
"s2">inf
</span>) *
2).asStream.nextN(
10);
</p>
54 <p class=
"p5"><br></p>
55 <p class=
"p6">// Random integers
1-
5, multiplied by
1/
4 gives multiples of
1/
4 between
0.25 and
1.25</p>
56 <p class=
"p4">(
<span class=
"s2">Pwhite
</span>(
1,
5,
<span class=
"s2">inf
</span>) *
0.25).asStream.nextN(
10);
</p>
57 <p class=
"p5"><br></p>
58 <p class=
"p6">// Random integers
1-
5, with the sign (positive or negative) randomly chosen
</p>
59 <p class=
"p4">(
<span class=
"s2">Pwhite
</span>(
1,
5,
<span class=
"s2">inf
</span>) *
<span class=
"s2">Prand
</span>(#[-
1,
1],
<span class=
"s2">inf
</span>)).asStream.nextN(
10);
</p>
60 <p class=
"p2"><br></p>
61 <p class=
"p3">If a binary operation occurs on two patterns, every time a value is requested from the resulting stream, both of the component streams are asked for a value, and the operator applies to those results. If either stream ends, the binary operator stream also ends.
</p>
62 <p class=
"p2"><br></p>
63 <p class=
"p6">// The resulting stream has two values, because the shorter operand stream has two values.
</p>
64 <p class=
"p4">(
<span class=
"s2">Pseq
</span>([
10,
9,
8],
1) +
<span class=
"s2">Pseq
</span>([
1,
2],
1)).do { |x| x.postln };
</p>
65 <p class=
"p2"><br></p>
66 <p class=
"p3">The binary operator adverb '.x' is supported with patterns. (See
<a href=
"../../Language/Adverbs.html"><span class=
"s1">Adverbs
</span></a>.) This adverb is like a nested loop: in streamA +.x streamB, the first value of streamA is added to every value of streamB in succession, then the second value of streamA is added to every streamB value, and so on. This is an easy way to transpose a pattern to different levels successively.
</p>
67 <p class=
"p2"><br></p>
68 <p class=
"p6">// Play a major-
7th arpeggio, transposed to different scale degrees
</p>
69 <p class=
"p6">// Pwhite is the transposer; Pseq is the chord
</p>
70 <p class=
"p6">// The chord is like an
"inner loop"</p>
72 <p class=
"p4">p =
<span class=
"s2">Pbind
</span>(
</p>
73 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s5">\midinote
</span>,
<span class=
"s2">Pwhite
</span>(
48,
72,
<span class=
"s2">inf
</span>) +.x
<span class=
"s2">Pseq
</span>(#[
0,
4,
7,
11],
1),
</p>
74 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s5">\dur
</span>,
0.125</p>
75 <p class=
"p4">).play;
</p>
77 <p class=
"p5"><br></p>
78 <p class=
"p4">p.stop;
</p>
79 <p class=
"p2"><br></p>
80 <p class=
"p2"><br></p>
81 <p class=
"p7"><b>Collection operations on patterns
</b></p>
82 <p class=
"p2"><br></p>
83 <p class=
"p3">Some of the things you can do to arrays also work with patterns.
</p>
84 <p class=
"p2"><br></p>
85 <p class=
"p3"><b>collect(func):
</b> Applies the function to each return value from the pattern. Good for generic transformations.
</p>
86 <p class=
"p3"><b>select(func):
</b> Preserve values from the output stream that pass the Boolean test; discard the rest.
</p>
87 <p class=
"p3"><b>reject(func):
</b> Discard values from the output stream that pass the test; return the rest to the user.
</p>
88 <p class=
"p2"><br></p>
89 <p class=
"p6">// Arbitrary/custom operation: Turn each number into a two-digit hex string
</p>
90 <p class=
"p4"><span class=
"s2">Pwhite
</span>(
0,
255,
20).collect({
<span class=
"s2">|x|
</span> x.asHexString(
2) }).do { |x| x.postln };
</p>
91 <p class=
"p5"><br></p>
92 <p class=
"p6">// Keep odd numbers in the result (which is now less than
20 items)
</p>
93 <p class=
"p4"><span class=
"s2">Pwhite
</span>(
0,
255,
20).select({
<span class=
"s2">|x|
</span> x.odd }).do { |x| x.postln };
</p>
94 <p class=
"p5"><br></p>
95 <p class=
"p6">// Throw out odd numbers in the result
</p>
96 <p class=
"p4"><span class=
"s2">Pwhite
</span>(
0,
255,
20).reject({
<span class=
"s2">|x|
</span> x.odd }).do { |x| x.postln };
</p>
97 <p class=
"p2"><br></p>
98 <p class=
"p3"><b>clump(n):
</b> Calling .clump on an array turns a flat array into a multilevel array. Similarly, .clump on a pattern gets
<i>n
</i> values from the pattern at once and returns all of them as an array.
<i>n
</i> can be a number or a numeric pattern.
</p>
99 <p class=
"p3"><b>flatten(levels):
</b> The reverse operation: if a pattern returns an array, its values will be output one by one.
</p>
100 <p class=
"p2"><br></p>
101 <p class=
"p6">// A flat stream becomes an array of
4-item arrays
</p>
102 <p class=
"p4"><span class=
"s2">Pwhite
</span>(
0,
255,
20).clump(
4).do { |x| x.postln };
</p>
103 <p class=
"p5"><br></p>
104 <p class=
"p6"><span class=
"s4"><span class=
"Apple-tab-span"> </span></span>// a two-dimensional array
</p>
105 <p class=
"p4"><span class=
"s2">Array
</span>.fill(
5, {
<span class=
"s2">Array
</span>.fill(
4, { rrand(
1,
5) }) });
</p>
106 <p class=
"p5"><br></p>
107 <p class=
"p6"><span class=
"s4"><span class=
"Apple-tab-span"> </span></span>// a pattern reading that array in sequence
</p>
108 <p class=
"p4">p =
<span class=
"s2">Pseq
</span>(
<span class=
"s2">Array
</span>.fill(
5, {
<span class=
"s2">Array
</span>.fill(
4, { rrand(
1,
5) }) }),
1);
</p>
109 <p class=
"p5"><br></p>
110 <p class=
"p6"><span class=
"s4"><span class=
"Apple-tab-span"> </span></span>// the pattern returns several arrays
</p>
111 <p class=
"p4">p.do { |x| x.postln };
</p>
112 <p class=
"p5"><br></p>
113 <p class=
"p6"><span class=
"s4"><span class=
"Apple-tab-span"> </span></span>// flattening the pattern returns a one-dimensional stream of numbers
</p>
114 <p class=
"p4">p.flatten.do { |x| x.postln };
</p>
115 <p class=
"p2"><br></p>
116 <p class=
"p3"><b>drop(n):
</b> Discard the first n values, and return whatever is left.
</p>
117 <p class=
"p2"><br></p>
118 <p class=
"p4"><span class=
"s2">Pseries
</span>(
1,
1,
20).drop(
5).do { |x| x.postln };
</p>
119 <p class=
"p2"><br></p>
120 <p class=
"p3"><b>differentiate:
</b> Return the difference between successive values: second - first, third - second, and so on.
</p>
121 <p class=
"p2"><br></p>
122 <p class=
"p4"><span class=
"s2">Array
</span>.geom(
20,
1,
1.01).differentiate;
</p>
123 <p class=
"p4"><span class=
"s2">Pgeom
</span>(
1,
1.01,
20).differentiate.do {
<span class=
"s2">|x|
</span> x.postln };
</p>
124 <p class=
"p2"><br></p>
125 <p class=
"p2"><br></p>
126 <p class=
"p7"><b>Miscellaneous calculation patterns
</b></p>
127 <p class=
"p2"><br></p>
128 <p class=
"p3">These are some other numeric calculations that don't exactly fall in the category of math operators.
</p>
129 <p class=
"p2"><br></p>
131 <li style=
"margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"><b>Pavaroh(pattern, aroh, avaroh, stepsPerOctave):
</b> Convert scale degrees to note numbers, with separate ascending and descending scale patterns. Originally written for Indian ragas, it also works well for the western melodic minor scale.
</li>
132 <li style=
"margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"><b>PdegreeToKey(pattern, scale, stepsPerOctave):
</b> Given a pattern yielding scale degrees, convert the degrees into note numbers according to the provided scale and steps per octave. This is done automatically when you use the 'degree' event key, but there might be cases where you would want to do some further math on the note numbers, and it might be necessary to make the conversion explicit.
</li>
133 <li style=
"margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"><b>Pdiff(pattern):
</b> Returns the difference between the source stream's latest and previous values. Among other uses, this can measure whether a stream is ascending or descending. This is the underlying implementation of the 'differentiate' method discussed just above.
</li>
134 <li style=
"margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"><b>Prorate(proportion, pattern):
</b> Splits up a number from 'pattern' according to proportion(s) given by the 'proportion' pattern. This is tricky to explain briefly; see the help file for some good examples.
</li>
136 <p class=
"p2"><br></p>
137 <p class=
"p6">// Swing notes with Prorate
</p>
139 <p class=
"p4">p =
<span class=
"s2">Pbind
</span>(
</p>
140 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s5">\degree
</span>,
<span class=
"s2">Pseries
</span>(
4,
<span class=
"s2">Pwhite
</span>(-
2,
2,
<span class=
"s2">inf
</span>).reject({
<span class=
"s2">|x|
</span> x ==
0 }),
<span class=
"s2">inf
</span>).fold(-
7,
11),
</p>
141 <p class=
"p6"><span class=
"s4"><span class=
"Apple-tab-span"> </span></span><span class=
"s5">\dur
</span><span class=
"s4">,
</span><span class=
"s2">Prorate
</span><span class=
"s4">(
0.6,
0.5)
<span class=
"Apple-tab-span"> </span></span>// actually yields
0.3,
0.2,
0.3,
0.2...
</p>
142 <p class=
"p4">).play;
</p>
144 <p class=
"p5"><br></p>
145 <p class=
"p4">p.stop;
</p>
146 <p class=
"p2"><br></p>
147 <p class=
"p2"><br></p>
148 <p class=
"p7"><b>Calculations based on other event values
</b></p>
149 <p class=
"p2"><br></p>
150 <p class=
"p3">In a Pbind, normally the patterns for the various keys calculate independently. But it's possible for one or more child patterns to depend on the result of another pattern inside the same Pbind. This is done with
<a href=
"../Patterns/Pkey.html"><span class=
"s1">Pkey
</span></a>, described in
<a href=
"PG_06g_Data_Sharing.html"><span class=
"s6">PG_06g_Data_Sharing
</span></a>.
</p>
151 <p class=
"p2"><br></p>
152 <p class=
"p8"><span class=
"s4">Previous:
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><a href=
"PG_04_Words_to_Phrases.html"><span class=
"s7">PG_04_Words_to_Phrases
</span></a></span></p>
153 <p class=
"p8"><span class=
"s4">Next:
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><a href=
"PG_060_Filter_Patterns.html"><span class=
"s7">PG_060_Filter_Patterns
</span></a></span></p>